package main

import (
	"fmt"
)

// 装饰器模式允许向一个现有的对象添加新的功能，同时又不改变其结构。

// Component 组件接口
type Component interface {
	Operation() string
}

// ConcreteComponent 具体组件
type ConcreteComponent struct{}

func (cc *ConcreteComponent) Operation() string {
	return "ConcreteComponent operation"
}

// Decorator 装饰器接口
type Decorator interface {
	Component
	SetComponent(component Component)
}

// ConcreteDecoratorA 具体装饰器 A
type ConcreteDecoratorA struct {
	component Component
}

func (cda *ConcreteDecoratorA) SetComponent(component Component) {
	cda.component = component
}

func (cda *ConcreteDecoratorA) Operation() string {
	return "ConcreteDecoratorA: " + cda.component.Operation()
}

// ConcreteDecoratorB 具体装饰器 B
type ConcreteDecoratorB struct {
	component Component
}

func (cdb *ConcreteDecoratorB) SetComponent(component Component) {
	cdb.component = component
}

func (cdb *ConcreteDecoratorB) Operation() string {
	return "ConcreteDecoratorB: " + cdb.component.Operation()
}

func main() {
	component := &ConcreteComponent{}

	decoratorA := &ConcreteDecoratorA{}
	decoratorA.SetComponent(component)

	fmt.Println(decoratorA.Operation())

	decoratorB := &ConcreteDecoratorB{}
	decoratorB.SetComponent(decoratorA)

	fmt.Println(decoratorB.Operation())
}
